/**
 * @Function 部门数据归集统计服务
 * @ProjectName credit-data-platform
 * @PackageName com.py.credit.service.impl
 * @FileName AchievementServiceImpl.java
 * @Date 2018年5月14日下午2:39:42
 * @Author Min DongXv
 * @Copyright (c) 2018, 金电联行 All Rights Reserved.
 */
package com.py.credit.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.py.credit.common.ServiceException;
import com.py.credit.common.logs.AccessLogger;
import com.py.credit.common.logs.ExceptionLogger;
import com.py.credit.common.rest.RestServiceResult;
import com.py.credit.dao.AchievementDao;
import com.py.credit.entity.AchievementCount;
import com.py.credit.entity.AchievementDetails;
import com.py.credit.entity.AreaRelationEntity;
import com.py.credit.entity.SysUser;
import com.py.credit.service.AchievementService;
import com.py.credit.service.RegionRelationService;
import com.py.credit.service.RemoteBaseService;
import com.py.credit.utils.DateUtil;
import com.py.credit.utils.SQLBuilder;
import com.py.framework.core.common.Page;
import com.py.framework.core.entity.SysAreaEntity;
import com.py.framework.core.entity.SysOfficeEntity;

/**
 * @Function 部门数据归集统计服务
 * @ClassName AchievementServiceImpl
 * @Date 2018年5月14日 下午2:39:42
 * @Author Min DongXv
 */
@Service
public class AchievementServiceImpl implements AchievementService {

	private static final String DEPTID = "deptId";
	private static final String RESOURCEID = "resourceId";
	private static final String SCOUNT = "scount";

	private static final int NUM_1000 = 1000;

	@Autowired
	private AchievementDao achievementDao;

	@Autowired
	private RemoteBaseService remoteBaseService;

	@Autowired
	private RegionRelationService regionRelationService;

	/**
	 * @param columns
	 * @param additionalColumns
	 * @param condition
	 * @param page
	 * @return
	 * @Function 分页查询归集部门统计概述
	 * @FileName AchievementServiceImpl.java
	 * @MethodName selectAchievementCountByConditionForPage
	 * @Date 11:03 18/7/20
	 * @Author Yaos
	 */
	@Override
	public List<Map<String, Object>> selectAchievementCountByConditionForPage(SysUser userInfo, List<String> columns,
			String[] additionalColumns, String condition, Page page) {
		List<String> conditions = SQLBuilder.createConditionSql(condition);
		Long topDeptId = userInfo.getOfficeId();
		// 获取父部门ID
		String pIds = userInfo.getAllParentId();
		if (StringUtils.isNotBlank(pIds)) {
			String t = StringUtils.split(pIds, ",")[0];
			topDeptId = StringUtils.isNoneBlank(t) ? Long.valueOf(t) : topDeptId;
		}
		Map<String, Object> params = new HashMap<>(4);
		params.put("regionId", userInfo.getAreaId());
		params.put("topDeptId", topDeptId);
		params.put("userType", userInfo.getUserType());
		params.put(DEPTID, userInfo.getOfficeId());
		return achievementDao.selectAchievementCountByConditionForPage(columns, additionalColumns, conditions, page,
				params);
	}

	/**
	 * @param columns
	 * @param additionalColumns
	 * @param deptID
	 * @param page
	 * @return
	 * @Function 分页查询归集部门统计详情
	 * @FileName AchievementServiceImpl.java
	 * @MethodName selectAchievementDetailsForPage
	 * @Date 11:04 18/7/20
	 * @Author Yaos
	 */
	@Override
	public List<Map<String, Object>> selectAchievementDetailsForPage(SysUser userInfo, List<String> columns,
			String[] additionalColumns, String condition, String dateRange, Page page, Integer udeptID) {
		List<String> conditions = SQLBuilder.createConditionSql(condition);
		Long topDeptId = userInfo.getOfficeId();
		// 获取父部门ID
		String pIds = userInfo.getAllParentId();
		if (StringUtils.isNotBlank(pIds)) {
			String t = StringUtils.split(pIds, ",")[0];
			topDeptId = StringUtils.isNoneBlank(t) ? Long.valueOf(t) : topDeptId;
		}
		Map<String, Object> params = new HashMap<String, Object>(8);
		params.put("regionId", userInfo.getAreaId());
		params.put("deptId", userInfo.getOfficeId());
		params.put("topDeptId", topDeptId);
		params.put("udeptID", udeptID);
		params.put("dateRange", dateRange);
		params.put("userType", userInfo.getUserType());
		String startTime = "";
		String endTime = "";
		DateUtil du = DateUtil.getInstance();
		Date date = null;
		try {
			SimpleDateFormat df = new SimpleDateFormat(DateUtil.YYYY_MM_DD);
			date = du.strToDate(dateRange + "01", DateUtil.YYYYMMDD);
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			calendar.set(Calendar.DAY_OF_MONTH, 1);
			startTime = df.format(calendar.getTime()) + " 00:00:00";
			calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
			endTime = df.format(calendar.getTime()) + " 23:59:59";
		} catch (ParseException e) {
			ExceptionLogger.error("时间转换异常", "时间转换异常", e);
		}

		params.put("startTime", StringUtils.isNotBlank(startTime) ? startTime : getDay(true, 0, 0));
		params.put("endTime", StringUtils.isNotBlank(endTime) ? endTime : getDay(true, 0, 1));
		List<Map<String, Object>> data = achievementDao.selectAchievementDetailsForPage(columns, additionalColumns,
				conditions, page, params);

		return data;
	}

	/**
	 * @return
	 * @Function 新增归集部门统计数据
	 * @FileName AchievementServiceImpl.java
	 * @MethodName addAchievementCount
	 * @Date 2018年5月14日 下午2:40:24
	 * @Author Min DongXv
	 */
	@Override
	public int addAchievementDetails(AchievementDetails achievementDetails) {
		AccessLogger.info("新增归集部门统计开始", "AchievementService#AchievementDetails Params:" + achievementDetails.toString(),
				"");
		int i = achievementDao.addAchievementDetails(achievementDetails);
		AccessLogger.info("新增归集部门统计结束", "AchievementService#AchievementDetails id:" + i, "");
		return i;
	}

	/**
	 * @return
	 * @Function 定时任务处理归集部门绩效统计详情并写入概述表
	 * @FileName AchievementServiceImpl.java
	 * @MethodName dealAchievementData
	 * @Date 2018年5月15日 上午9:39:58
	 * @Author Min DongXv
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void dealAchievementData() {
		Calendar calendar = Calendar.getInstance();
		LocalDate date = LocalDate.now();
		DateTimeFormatter dTF = DateTimeFormatter.ofPattern("uuuuMM");
		String dateRange = dTF.format(date);
		List<AchievementDetails> ddata = new ArrayList<AchievementDetails>();
		RestServiceResult<List<SysOfficeEntity>> allDepts = remoteBaseService.getOfficesByAreaId(null, null);
		// 远程调用获取所有部门信息异常，返回异常
		if (CollectionUtils.isEmpty(allDepts.getData())) {
			ExceptionLogger.error("AchievementService#dealAchievementDetailsData", "获取所有部门信息异常,无返回数据！");
			throw new ServiceException("系统异常，请稍后再试！");
		}
		// 获取所有区域信息
		RestServiceResult<List<SysAreaEntity>> allAreas = remoteBaseService.getAllAreas(null, null);
		// 处理区域资源对应关系
		Map<Long, AreaRelationEntity> regionResources = regionRelationService.dealRegionResource(allAreas);
		// 处理部门资源对应关系
		Map<Long, Set<String>> deptResources = regionRelationService.dealDeptResource(regionResources,
				allDepts.getData());

		// 获取更新频率为月度的数据
		AccessLogger.info("定时任务处理归集部门绩效统计->获取更新频率为月度的数据", "AchievementService#dealAchievementDetailsData", "");
		List<Map<String, Object>> mData = achievementDao.selectAchievementDetailsData(new String[] { "M" },
				getDay(true, 0, 0), getDay(true, 0, 1));
		if (!CollectionUtils.isEmpty(mData)) {
			// 组装Details实体
			for (Map<String, Object> m : mData) {
				Long id = Long.parseLong(String.valueOf(m.get(DEPTID)));
				String resourceId = String.valueOf(m.get(RESOURCEID));
				// 存在的才统计
				Set<String> set = deptResources.get(id);
				if (deptResources.containsKey(id) && !CollectionUtils.isEmpty(set) && set.contains(resourceId)) {
					AchievementDetails details = new AchievementDetails();
					details.setDateRange(dateRange);
					details.setDeptId(id);
					details.setResourceId(Long.parseLong(resourceId));
					Integer scount = Integer.parseInt(String.valueOf(null == m.get(SCOUNT) ? 0 : m.get(SCOUNT)));
					details.setScount(scount);
					details.setFrequency("M");
					details.setIsAchieve(scount > 0 ? "Y" : "N");
					ddata.add(details);
				}
			}
		}
		// 计算季度的开始月份和结束月份
		int start = (calendar.get(Calendar.MONTH) / 3) * 3 + 1;
		int endMonth = start + 2;
		// 获取更新频率为季度的数据
		AccessLogger.info("定时任务处理归集部门绩效统计->获取更新频率为季度的数据", "AchievementService#dealAchievementDetailsData", "");
		List<Map<String, Object>> qData = achievementDao.selectAchievementDetailsData(new String[] { "Q" },
				getDay(true, start, 0), getDay(true, endMonth, 1));

		if (!CollectionUtils.isEmpty(qData)) {
			for (Map<String, Object> m : mData) {
				Long id = Long.parseLong(String.valueOf(m.get(DEPTID)));
				String resourceId = String.valueOf(m.get(RESOURCEID));
				// 存在的才统计
				Set<String> set = deptResources.get(id);
				if (deptResources.containsKey(id) && !CollectionUtils.isEmpty(set) && set.contains(resourceId)) {
					AchievementDetails details = new AchievementDetails();
					details.setDateRange(dateRange);
					details.setDeptId(id);
					details.setResourceId(Long.parseLong(resourceId));
					Integer scount = Integer.parseInt(String.valueOf(null == m.get(SCOUNT) ? 0 : m.get(SCOUNT)));
					details.setScount(scount);
					details.setFrequency("Q");
					details.setIsAchieve(scount > 0 ? "Y" : "N");
					ddata.add(details);
				}
			}
		}
		// 获取更新频率为年度的数据
		AccessLogger.info("定时任务处理归集部门绩效统计->获取更新频率为年度的数据", "AchievementService#dealAchievementDetailsData", "");
		List<Map<String, Object>> yData = achievementDao.selectAchievementDetailsData(new String[] { "Y" },
				getDay(true, 1, 0), getDay(true, 12, 1));
		if (!CollectionUtils.isEmpty(yData)) {
			for (Map<String, Object> m : mData) {
				Long id = Long.parseLong(String.valueOf(m.get(DEPTID)));
				String resourceId = String.valueOf(m.get(RESOURCEID));
				// 存在的才统计
				Set<String> set = deptResources.get(id);
				if (deptResources.containsKey(id) && !CollectionUtils.isEmpty(set) && set.contains(resourceId)) {
					AchievementDetails details = new AchievementDetails();
					details.setDateRange(dateRange);
					details.setDeptId(id);
					details.setResourceId(Long.parseLong(resourceId));
					Integer scount = Integer.parseInt(String.valueOf(null == m.get(SCOUNT) ? 0 : m.get(SCOUNT)));
					details.setScount(scount);
					details.setFrequency("Y");
					details.setIsAchieve(scount > 0 ? "Y" : "N");
					ddata.add(details);
				}
			}
		}
		// 获取更新频率为实时，每天，每周数据
		AccessLogger.info("定时任务处理归集部门绩效统计->获取更新频率为实时，每天，每周数据", "AchievementService#dealAchievementDetailsData", "");
		List<Map<String, Object>> oData = achievementDao.selectAchievementDetailsData(new String[] { "S", "D", "W" },
				getDay(true, 0, 0), getDay(true, 0, 1));
		if (!CollectionUtils.isEmpty(oData)) {
			// 组装Details实体
			for (Map<String, Object> m : oData) {
				Long id = Long.parseLong(String.valueOf(m.get(DEPTID)));
				String resourceId = String.valueOf(m.get(RESOURCEID));
				// 存在的才统计
				Set<String> set = deptResources.get(id);
				if (deptResources.containsKey(id) && !CollectionUtils.isEmpty(set) && set.contains(resourceId)) {
					AchievementDetails details = new AchievementDetails();
					details.setDateRange(dateRange);
					details.setDeptId(id);
					details.setResourceId(Long.parseLong(resourceId));
					Integer scount = Integer.parseInt(String.valueOf(null == m.get(SCOUNT) ? 0 : m.get(SCOUNT)));
					details.setScount(scount);
					details.setFrequency(String.valueOf(m.get("updateFrequency")));
					details.setIsAchieve("Z");
					ddata.add(details);
				}
			}
		}
		if (!CollectionUtils.isEmpty(ddata)) {
			if (!CollectionUtils.isEmpty(mData)) {
				// 删除月度数据
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除月度数据开始",
						"AchievementService#dealAchievementDetailsData#deleteMonthDetails", "");
				achievementDao.deleteMonthCount(dateRange);
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除月度数据结束",
						"AchievementService#dealAchievementDetailsData#deleteMonthDetails", "");
			}
			if (!CollectionUtils.isEmpty(qData)) {
				// 删除季度数据
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除季度数据开始",
						"AchievementService#dealAchievementCountData#deleteQuarterCount", "");
				String[] months = new String[] { "01", "02", "04", "05", "07", "08", "10", "11",
						String.valueOf(dateRange.substring(4, 5)) };
				achievementDao.deleteQuarterCount(dateRange, months);
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除季度数据结束",
						"AchievementService#dealAchievementDetailsData#deleteQuarterDetails", "");
			}
			if (!CollectionUtils.isEmpty(yData)) {
				// 删除年度数据
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除年度数据开始",
						"AchievementService#dealAchievementDetailsData#deleteYearDetails", "");
				achievementDao.deleteYearCount(dateRange);
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除年度数据结束",
						"AchievementService#dealAchievementDetailsData#deleteYearDetails", "");
			}
			if (!CollectionUtils.isEmpty(oData)) {
				// 删除实时，每天，每周数据
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除实时，每天，每周数据开始",
						"AchievementService#dealAchievementDetailsData#deleteOtherDetails", "");
				achievementDao.deleteOtherCount(dateRange);
				AccessLogger.info("定时任务处理归集部门绩效统计详情->删除实时，每天，每周数据结束",
						"AchievementService#dealAchievementDetailsData#deleteOtherDetails", "");
			}
			AccessLogger.info("定时任务处理归集部门绩效统计详情->分批次批量插入数据开始",
					"AchievementService#dealAchievementDetailsData#batchAddAchievementDetails", "");
			// 分批次批量插入
			if (ddata.size() > NUM_1000) {
				int num = ddata.size() / NUM_1000;
				for (int i = 0; i < num; i++) {
					achievementDao.batchAddAchievementDetails(ddata.subList(0 + i * NUM_1000, 999 + i * NUM_1000));
				}
				achievementDao.batchAddAchievementDetails(ddata.subList(num * NUM_1000, ddata.size()));
			} else {
				achievementDao.batchAddAchievementDetails(ddata);
			}
			AccessLogger.info("定时任务处理归集部门绩效统计->分批次批量插入数据结束",
					"AchievementService#dealAchievementDetailsData#batchAddAchievementDetails", "");
		}

		// 写入概述表
		List<AchievementCount> cdata = new ArrayList<AchievementCount>();
		// 查询当期统计概述
		List<Map<String, Object>> countByDateRange = achievementDao.selectAchievementCountByDateRange(dateRange);

		if (!CollectionUtils.isEmpty(countByDateRange)) {
			// 组装Count实体
			for (Map<String, Object> dat : countByDateRange) {
				Long deptId = Long.parseLong(String.valueOf(dat.get("deptId")));
				Long countTable = Long.parseLong(String.valueOf(dat.get("countTable")));
				Long countResource = Long.parseLong(String.valueOf(dat.get("countResource")));
				Integer sumScount = Integer.parseInt(String.valueOf(dat.get("sumScount")));
				String isAchieve = String.valueOf(String.valueOf(dat.get("isAchieve")));

				AchievementCount count = new AchievementCount();
				count.setDateRange(dateRange);
				count.setDeptId(deptId);
				count.setCountTable(countTable);
				count.setCountResource(countResource);
				count.setSumScount(sumScount);
				count.setIsAchieve(decideIsAchieve(isAchieve));
				cdata.add(count);
			}
		}
		if (!CollectionUtils.isEmpty(cdata)) {
			AccessLogger.info("定时任务处理归集部门绩效概述->删除数据开始", "AchievementService#dealAchievementCountData#deleteMonthCount",
					"");
			achievementDao.deleteAchievementCount(dateRange);
			AccessLogger.info("定时任务处理归集部门绩效概述->删除数据结束", "AchievementService#dealAchievementCountData#deleteMonthCount",
					"");
			// 传数据
			AccessLogger.info("定时任务处理归集部门绩效概述->写入数据开始", "AchievementService#dealAchievementCountData#start", "");
			achievementDao.insertAchievementCount(cdata);
			AccessLogger.info("定时任务处理归集部门绩效概述->写入数据结束", "AchievementService#dealAchievementCountData#end", "");
		}

	}

	/**
	 * @param isAchieve
	 * @Function 判断isAchieve
	 * @FileName AchievementServiceImpl.java
	 * @Enum 绩效任务 Y:是 N:否 R:进行中 Z:暂不处理
	 * @Date 16:19 18/7/20
	 * @Author Yaos
	 */
	private String decideIsAchieve(String isAchieve) {
		if (isAchieve.contains("N")) {
			return "N";
		} else if (isAchieve.contains("Y")) {
			return "Y";
		} else if (isAchieve.contains("R")) {
			return "R";
		} else {
			return "Z";
		}
	}

	/**
	 * @param isNeedHH24MISS
	 *            是否需要时分秒
	 * @param month
	 *            月份
	 * @param flag
	 *            0开始时间 1结束时间
	 * @return
	 * @Function 获取时间
	 * @FileName AchievementServiceImpl.java
	 * @MethodName getDay
	 * @Date 2018年5月15日 上午9:39:58
	 * @Author Min DongXv
	 */
	private String getDay(boolean isNeedHH24MISS, int month, int flag) {
		SimpleDateFormat df = new SimpleDateFormat(DateUtil.YYYY_MM_DD);
		Calendar calendar = Calendar.getInstance();
		Date theDate = calendar.getTime();
		GregorianCalendar gcLast = (GregorianCalendar) Calendar.getInstance();
		gcLast.setTime(theDate);
		if (0 < month) {
			gcLast.set(Calendar.MONTH, month);
		}
		if (0 == flag) {
			// 设置为当月第一天
			gcLast.set(Calendar.DAY_OF_MONTH, 1);
		}
		if (1 == flag) {
			// 设置为当月最后一天
			gcLast.set(Calendar.DAY_OF_MONTH, gcLast.getActualMaximum(Calendar.DAY_OF_MONTH));
		}
		String dayFirst = df.format(gcLast.getTime());
		StringBuilder str = new StringBuilder().append(dayFirst);
		if (isNeedHH24MISS) {
			if (0 == flag) {
				str.append(" 00:00:00");
			}
			if (1 == flag) {
				str.append(" 23:59:59");
			}
		}
		return str.toString();
	}
}
